<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
<script>

// var sayHi = function(who){
// 	return "Hello" + (who ? ", " + who : "") + "!";
// }

// //调用函数（called or invoked）
// console.log(sayHi());	//Hello!
// console.log(sayHi("kathy"));	//Hello, kathy!
// //应用函数 （applied）使用方法Function.prototype.apply()
// //第一个参数————将要绑定到该函数内部this的一个对象，如果为null，this-->全局对象
// //第二个参数————一个数组或多个参数变量，这些参数将变成可用于该函数内部的类似数组的arguments对象
// console.log(sayHi.apply(null, ["kathy"]));	//Hello, kathy!




// var age = 20;
// var alien = {
// 	age : 15,
// 	sayHi : function(who){
// 		return "Hello" + (who ? ", " + who : "") + "! And you're " + this.age + " year's old ?";
// 	}
// };
// console.log(alien.sayHi("xuxuan")); //Hello, xuxuan! And you're 15 year's old ? 
// console.log(alien.sayHi.apply(alien,["xuxuan"]));	//Hello, xuxuan! And you're 15 year's old ? 
// console.log(alien.sayHi.apply(null,["xuxuan"]));	//Hello, xuxuan! And you're 20 year's old ? 
// // console.log(sayHi("xuxuan"));	 //Uncaught ReferenceError: sayHi is not defined 
// // console.log(sayHi.apply(alien,["xuxuan"])); //Uncaught ReferenceError: sayHi is not defined 
// // console.log(sayHi.apply(null,["xuxuan"]));	//Uncaught ReferenceError: sayHi is not defined 


/*
var age = 20;
var Alien = function(){
	this.age = 15;
	this.sayHi = function(who){
		return "Hello" + (who ? ", " + who : "") + "! And you're " + this.age + " year's old ?";
	};
};
var alien = new Alien();
console.log(alien.sayHi("xuxuan"));	//Hello, xuxuan! And you're 15 year's old ? 
console.log(alien.sayHi.apply(alien,["xuxuan"]));	//Hello, xuxuan! And you're 15 year's old ? 
console.log(alien.sayHi.apply(null,["xuxuan"]));	//Hello, xuxuan! And you're 20 year's old ? 

console.log(alien.sayHi.call(alien,"xuxuan"));	//Hello, xuxuan! And you're 15 year's old ? 
console.log(alien.sayHi.call(null,"xuxuan"));	//Hello, xuxuan! And you're 20 year's old ? */

/*
function add(x, y){
	var oldx = x, oldy = y;
	//部分
	if(typeof oldy === "undefined"){
		return function(newly){
			return oldx + newly;
		}
	}
	//完全应用
	return x + y;
}*/

/*//更为精简的实现版本
function add(x, y){
	//部分
	if(typeof y === "undefined"){
		return function(y){
			return x + y;
		}
	}
	//完全应用
	return x + y;
}

console.log(typeof add(5)); //function
console.log(add(3)(4));  //7

//add2000是一个新函数
var add2000 = add(2000);
console.log(add2000(13));  //2013

*/

/*
//更通用的方式，将任意函数转换成一个新的可以接受部分参数的函数
function schonfinkelize(fn){
	var slice = Array.prototype.slice,
		stored_args = slice.call(arguments, 1);
	return function(){
		var new_args = slice.call(arguments),
			args = stored_args.concat(new_args);
		return fn.apply(null, args);
	};
}

//---------------------------------------------------------------

//普通函数
function add(x, y){
	return x + y;
}

//将一个函数curry化以获得一个新的函数
var newadd = schonfinkelize(add, 5);
console.log(newadd(4));  //9

//另一种用法————直接调用新函数
console.log(schonfinkelize(add,5)(4)); //9

//---------------------------------------------------------------

//普通函数
function add2(a, b, c, d, e){
	return a + b + c + d + e;
}

//两步curry化
var addOne = schonfinkelize(add2, 1);
console.log(addOne(10, 10, 10, 10));  //41

var addTow = schonfinkelize(addOne, 2, 3);  //addOne函数只用传递4个参数
console.log(addTow(5,5));  //16

//可运行于任意数量的参数
console.log(schonfinkelize(add2, 1, 2, 3)(5, 5));  //16

*/


/*
//5个全局变量
//反模式
//构造函数
function Parent(){}
function Child(){}

//一个变量
var some_var = 1 ;

//一些对象
var module1 = {};
module1.data = {
	a : 1,
	b : 2
};
var module2 = {};



//1个全局变量
//重构上述代码，创建一个全局对象MYAPP，改变所有函数和变量成为这个全局对象的属性
var MYAPP ={};
MYAPP.Parent = function(){};
MYAPP.Child = function(){};
MYAPP.some_var = 1;
//一个容器对象
MYAPP.modules = {};
//嵌套对象
MYAPP.modules.module1 = {};
MYAPP.modules.module1.data = {a:1, b:2};
MYAPP.modules.module2 = {};


//不安全的代码
var MYAPP = {};

//更好的代码风格
if(typeof MYAPP === "undefined"){
	mar MYAPP = {};
}
//或者用更短的语句
var MYAPP = MYAPP || {};*/

/*var MYAPP = MYAPP || {};
MYAPP.namespace = function(ns_string){
	var parts = ns_string.split("."),
		parent = MYAPP,
		i;

	//剥离最前面的冗余全局变量
	if(parts[0] === "MYAPP"){
		parts = parts.slice(1);
	}

	for(i=0; i<parts.length; i++){
		//如果它不存在，就创建一个属性
		if(typeof parent[parts[i]] === "undefined"){
			parent[parts[i]] = {};
		}
		parent = parent[parts[i]];
	}
	return parent;
}

//将返回值赋给一个局部变量
var module2 = MYAPP.namespace('MYAPP.modules.module2');
console.log(module2 === MYAPP.modules.module2); //true

MYAPP.namespace('modules.module2');
MYAPP.namespace("once.upon.a.time");*/

/*function myFunc = function(){
	//依赖
	var event = YAHOO.util.Event,
		dom = YAHOO.util.dom;

	//使用event和dom对象
}*/

/*function Gadget(){
	//私有成员
	var name = "kathy";
	//共有函数
	this.getName = function(){
		return name;
	}
}

var toy = new Gadget();
console.log(toy.name);	//undefined
console.log(toy.getName());	//kathy*/

/*function Gadget() {
	// private member
	var specs = {
		screen_width: 320,
		screen_height: 480,
		color: "white"
	};
	// public function
	this.getSpecs = function () {
		return specs;
	};
}

var toy = new Gadget(),
	specs = toy.getSpecs();
specs.color = "black";
specs.price = "free";
console.dir(toy.getSpecs());*/

/*
function Gadget(){
	var name = "iPod";
	this.getName = function(){
		return name;
	};
}

Gadget.prototype = (function(){
	var browser = "Mobile Webkit";
	return {
		getBrowser : function(){
			return browser;
		}
	}
}());

var toy = new Gadget();
// privileged "own" method
console.log(toy.getName());		//iPod
// privileged prototype method
console.log(toy.getBrowser());	//Mobile Webkit*/


// var myarray;
// (function(){
	
// 	var astr = "[object Array]",
// 		toString = Object.prototype.toString;

// 	function isArray(a){
// 		return toString.call(a) === astr;
// 	}

// 	function indexOf(haystack, needle){
// 		var i = 0,
// 			max = haystack.length;
// 		for(; i<max; i++){
// 			if(haystack[i] === needle){
// 				return i;
// 			}
// 		}
// 		return -1;
// 	}

// 	myarray = {
// 		isArray : isArray,
// 		indexOf : indexOf,
// 		inArray : indexOf
// 	}

// }());

// console.log(myarray.isArray([1,2]));//true
// console.log(myarray.isArray({o:[1,2]}));//false
// console.log(myarray.indexOf(["a","d","z"],"z"));//2
// console.log(myarray.inArray(["a","d","z"],"z"));//2

// //如果发生意外，例如公用方法indexOf()挂了，但是私有的indexOf()还是安全滴，所以inArray()正常运行
// myarray.indexOf = null;
// console.log(myarray.inArray([3,4,5],3));//0

/*//返回一个数值
var result = (function(){
	return 2 + 2;
}());

//另一种方式忽略包装函数的括号，因为将及时函数的返回值分配给一个变量时并不需要这些括号
var result = function(){
	return 2 + 2;
}();

//返回一个函数
var getResult = (function(){
	var res = 2 + 2;
	return function(){
		return res;
	};
}());
console.log(getResult());

//当定义对象属性也可以用即时函数
//场景：需要定义一个对象在生命周期内永远不会改变的属性，但是在定义之前需要执行一些工作以找出正确的值，
//此时，使用即时函数包装这些工作，返回值将会成为属性值
var o = {
	message : (function(){
		var who = "me",
			what = "call";
		return what + " " + who;
	}()),
	getMsg : function(){
		return this.message;
	}
};

console.log(o.getMsg()); //call me
console.log(o.message); //call me*/


({
	// here you can define setting values
	// a.k.a. configuration constants
	maxwidth: 600,
	maxheight: 400,
	// you can also define utility methods
	gimmeMax: function () {
		return this.maxwidth + "x" + this.maxheight;
	},
	// initialize
	init: function () {
		console.log(this.gimmeMax());
		// more init tasks...
	}
}).init();

// BEFORE
var utils = {
	addListener: function (el, type, fn) {
		if (typeof window.addEventListener === 'function') {
			el.addEventListener(type, fn, false);
		} else if (typeof document.attachEvent === 'function') { // IE
			el.attachEvent('on' + type, fn);
		} else { // older browsers
			el['on' + type] = fn;
		}
	},
	removeListener: function (el, type, fn) {
		// pretty much the same...
	}
};



// AFTER
// the interface
var utils = {
	addListener: null,
	removeListener: null
};
// the implementation
if (typeof window.addEventListener === 'function') {
	utils.addListener = function (el, type, fn) {
		el.addEventListener(type, fn, false);
	};
	utils.removeListener = function (el, type, fn) {
		el.removeEventListener(type, fn, false);
	};
} else if (typeof document.attachEvent === 'function') { // IE
	utils.addListener = function (el, type, fn) {
		el.attachEvent('on' + type, fn);
	};
	utils.removeListener = function (el, type, fn) {
		el.detachEvent('on' + type, fn);
	};
} else { // older browsers
	utils.addListener = function (el, type, fn) {
		el['on' + type] = fn;
	};
	utils.removeListener = function (el, type, fn) {
		el['on' + type] = null;
	};
}

var myFunc = function () {
	var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),
		result;
	if (!myFunc.cache[cachekey]) {
		result = {};
		// ... expensive operation ...
		myFunc.cache[cachekey] = result;
	}
	return myFunc.cache[cachekey];
};
// cache storage
myFunc.cache = {};


var myFunc = function (param) {
	var f = arguments.callee,
	result;
	if (!f.cache[param]) {
		result = {};
		// ... expensive operation ...
		f.cache[param] = result;
	}
	return f.cache[param];
};
// cache storage
myFunc.cache = {};




var conf = {
	username: "batman",
	first: "Bruce",
	last: "Wayne"
};
addPerson(conf);



</script>
</body>
</html>